/*
* coder: Dzlua
* email: 505544956@qq.com
* time : 2018-04-10 18:40
*/
#pragma once
#ifndef __SINGLETON_HPP__
#define __SINGLETON_HPP__

#include <memory>

UI_BEGIN_NAMESPACE

/*
* You should use it like this:
*   class MyCls : public ui::CSingleton<MyCls>
    {
    public:
        MyCls(int i) : m_n(i) {}
        void print() { std::cout << m_n << std::endl; }
        int m_n;
    };

    int main(int argc, char** argv)
    {
        // you must call this function at least once before use it.
        auto a = MyCls::init_instance(10);
        a->print();

        // use this function to get a instance.
        auto b = MyCls::instance();
        b->print();
        return 0;
    }

    see: test/utils/singleton.cpp
*/
template <typename T>
class CSingleton {
protected:
    /*
    * The copy constructor and the operator
    * are also private to prevent duplication.
    */
   UI_CLASS_NO_CONSTRUCTOR(CSingleton)
   UI_CLASS_NO_COPY(CSingleton)
public:
    // you must call this function at least once before use it.
    template <typename... Args>
    static auto init_instance(Args&&... args) {
        if (!p_) {
            p_ = std::make_shared<T>(std::forward<Args>(args)...);
        }
        return p_;
    }

    // use this function to get a instance.
    static auto instance() {
        /*
        * Have you ever called init_initance ?
        */
        return p_;
    }
private:
    static std::shared_ptr<T> p_;
};

template <typename T> std::shared_ptr<T> CSingleton<T>::p_ = nullptr;

UI_END_NAMESPACE

#endif
